"use strict";

const path = require("path");
const fs = require("fs");
const { exec } = require("child_process");
const { Controller } = require("ee-core");
const { app: electronApp, shell } = require("electron");
const dayjs = require("dayjs");
const Ps = require("ee-core/ps");
const Log = require("ee-core/log");
const Services = require("ee-core/services");
const Conf = require("ee-core/config");
const Addon = require("ee-core/addon");
const EE = require("ee-core/ee");
const treeKill = require("tree-kill");

let batProcessMap = new Map();
let num = 0;
/**
 * electron-egg framework - 功能demo
 * @class
 */
class FrameworkController extends Controller {
  constructor(ctx) {
    super(ctx);
  }

  /**
   * 所有方法接收两个参数
   * @param args 前端传的参数
   * @param event - ipc通信时才有值。详情见：控制器文档
   */

  /**
   * json数据库操作
   */
  async jsondbOperation(args) {
    const {
      action,
      info,
      delete_name,
      update_name,
      update_age,
      search_age,
      data_dir,
    } = args;

    const data = {
      action,
      result: null,
      all_list: [],
    };

    switch (action) {
      case "add":
        data.result = await Services.get("database.jsondb").addTestData(info);
        break;
      case "del":
        data.result =
          await Services.get("database.jsondb").delTestData(delete_name);
        break;
      case "update":
        data.result = await Services.get("database.jsondb").updateTestData(
          update_name,
          update_age
        );
        break;
      case "get":
        data.result =
          await Services.get("database.jsondb").getTestData(search_age);
        break;
      case "getDataDir":
        data.result = await Services.get("database.jsondb").getDataDir();
        break;
      case "setDataDir":
        data.result =
          await Services.get("database.jsondb").setCustomDataDir(data_dir);
        break;
    }

    data.all_list = await Services.get("database.jsondb").getAllTestData();

    return data;
  }

  /**
   * sqlite数据库操作
   */
  async sqlitedbOperation(args) {
    const {
      action,
      info,
      delete_name,
      update_name,
      update_age,
      search_age,
      data_dir,
    } = args;

    const data = {
      action,
      result: null,
      all_list: [],
      code: 0,
    };

    try {
      // test
      Services.get("database.sqlitedb").getDataDir();
    } catch (err) {
      console.log(err);
      data.code = -1;
      return data;
    }

    switch (action) {
      case "add":
        data.result =
          await Services.get("database.sqlitedb").addTestDataSqlite(info);
        break;
      case "del":
        data.result =
          await Services.get("database.sqlitedb").delTestDataSqlite(
            delete_name
          );
        break;
      case "update":
        data.result = await Services.get(
          "database.sqlitedb"
        ).updateTestDataSqlite(update_name, update_age);
        break;
      case "get":
        data.result =
          await Services.get("database.sqlitedb").getTestDataSqlite(search_age);
        break;
      case "getDataDir":
        data.result = await Services.get("database.sqlitedb").getDataDir();
        break;
      case "setDataDir":
        data.result =
          await Services.get("database.sqlitedb").setCustomDataDir(data_dir);
        break;
      case "list":
        data.result = await Services.get("database.sqlitedb").list();
        break;
      case "save":
        data.result = await Services.get("database.sqlitedb").save(info);
        break;
      case "remove":
        data.result = await Services.get("database.sqlitedb").remove();
        break;
      case "page":
        data.result = await Services.get("database.sqlitedb").page(info);
        break;
    }

    return data;
  }

  /**
   * 调用其它程序（exe、bash等可执行程序）
   *
   */
  openSoftware(softName) {
    if (!softName) {
      return false;
    }

    let softwarePath = path.join(Ps.getExtraResourcesDir(), softName);
    Log.info("[openSoftware] softwarePath:", softwarePath);

    // 检查程序是否存在
    if (!fs.existsSync(softwarePath)) {
      return false;
    }
    // 命令行字符串 并 执行, start 命令后面的路径要加双引号
    let cmdStr = `start "${softwarePath}"`;
    exec(cmdStr);

    // 方法二
    // 推荐使用cross模块

    return true;
  }

  /**
   * 执行bat文件
   *
   */
  openBatFile(obj) {
    console.log("openBatFile====", obj.batPath);
    console.log("openBatFile====", obj.videoPath);
    console.log("openBatFile====", obj.outfolderName);
    if (JSON.stringify(obj) == "{}") {
      return false;
    }

    // 命令行字符串 并 执行, start 命令后面的路径要加双引号
    exec(
      `start ${obj.batPath} ${obj.videoPath} ${obj.outfolderName}`,
      (error, stdout, stderr) => {
        if (error) {
          console.error(`执行的错误: ${error}`);
          return;
        }

        console.log(`stdout: ${stdout}`);
        console.error(`stderr: ${stderr}`);
        return true;
      }
    );
    // exec('start D:\\ms-ge.bat D:\\test.mp4', (error, stdout, stderr) => {
    //   if (error) {
    //     console.error(`执行的错误: ${error}`);
    //     return;
    //   }
    //   console.log(`stdout: ${stdout}`);
    //   console.error(`stderr: ${stderr}`);
    // });
  }

  //
  startCmd(batPath) {
    if (!batPath) {
      return false;
    }
    const cmdStr = `start ${batPath}`;
    console.log("cmd====", cmdStr);
    const proc = exec(
      cmdStr,
      {
        windowsHide: false,
        shell: false,
      },
      (error, stdout, stderr) => {
        if (error) {
          console.log("exec error:", error);
          return false;
        }
      }
    );
    num = 6;
    batProcessMap.set(proc.pid, proc);
    return true;
  }

  stopCmd() {
    console.log("batProcessMap----", batProcessMap);
    if (batProcessMap.size > 0) {
      console.log("this.num----", num);
      batProcessMap.forEach((proc, pid) =>{
        exec(`taskkill /PID ${pid} /F`)
        // treeKill(pid,"SIGINT", (err) => {
        //   console.log("treeKill err----", err);
        //   if(!err){
        //     batProcessMap.delete(pid)
        //   }
        // })
      });
      batProcessMap.clear();
    }
  }

  /**
   * 检查folderPath文件夹中是否存在filename文件
   */
  checkFileExists({ folderPath, fileName }) {
    console.log("checkFileExists====", folderPath, fileName);
    // 构建完整的文件路径
    const filePath = path.join(folderPath, fileName);

    console.log("filePath", filePath);
    // 尝试访问文件
    fs.access(filePath, fs.constants.F_OK, (err) => {
      console.log("err", !err);
      return !err;
    });
  }

  /**
   * 检查是否有新版本
   */
  checkForUpdater() {
    Addon.get("autoUpdater").checkUpdate();
    return;
  }

  /**
   * 下载新版本
   */
  downloadApp() {
    Addon.get("autoUpdater").download();
    return;
  }

  /**
   * 检测http服务是否开启
   */
  async checkHttpServer() {
    const httpServerConfig = Conf.getValue("httpServer");
    const url =
      httpServerConfig.protocol +
      httpServerConfig.host +
      ":" +
      httpServerConfig.port;

    const data = {
      enable: httpServerConfig.enable,
      server: url,
    };
    return data;
  }

  /**
   * 一个http请求访问此方法
   */
  async doHttpRequest() {
    const { CoreApp } = EE;
    // http方法
    const method = CoreApp.request.method;
    // http get 参数
    let params = CoreApp.request.query;
    params =
      params instanceof Object ? params : JSON.parse(JSON.stringify(params));
    // http post 参数
    const body = CoreApp.request.body;

    const httpInfo = {
      method,
      params,
      body,
    };
    Log.info("httpInfo:", httpInfo);

    if (!body.id) {
      return false;
    }
    const dir = electronApp.getPath(body.id);
    shell.openPath(dir);

    return true;
  }

  /**
   * 一个socket io请求访问此方法
   */
  async doSocketRequest(args) {
    if (!args.id) {
      return false;
    }
    const dir = electronApp.getPath(args.id);
    shell.openPath(dir);

    return true;
  }

  /**
   * 异步消息类型
   */
  async ipcInvokeMsg(args, event) {
    let timeNow = dayjs().format("YYYY-MM-DD HH:mm:ss");
    const data = args + " - " + timeNow;

    return data;
  }

  /**
   * 同步消息类型
   */
  async ipcSendSyncMsg(args) {
    let timeNow = dayjs().format("YYYY-MM-DD HH:mm:ss");
    const data = args + " - " + timeNow;

    return data;
  }

  /**
   * 双向异步通信
   */
  async ipcSendMsg(args, event) {
    const { type, content } = args;
    const data = await Services.get("framework").bothWayMessage(
      type,
      content,
      event
    );

    return data;
  }

  /**
   * 上传文件
   * 不建议使用，请使用electron的api来获取文件的本机路径，然后读取并上传
   * 使用http的files属性，实际上多余拷贝一次文件
   */
  async uploadFile() {
    const { CoreApp } = EE;
    let tmpDir = Ps.getLogDir();
    const files = CoreApp.request.files;
    let file = files.file;

    let tmpFilePath = path.join(tmpDir, file.originalFilename);
    try {
      let tmpFile = fs.readFileSync(file.filepath);
      fs.writeFileSync(tmpFilePath, tmpFile);
    } finally {
      await fs.unlink(file.filepath, function () {});
    }
    const fileStream = fs.createReadStream(tmpFilePath);
    const uploadRes =
      await Services.get("framework").uploadFileToSMMS(fileStream);

    return uploadRes;
  }

  /**
   * 废弃，请使用 cross 模块
   * 启动java项目
   */
  async startJavaServer() {
    let data = {
      code: 0,
      msg: "",
      server: "",
    };
    const javaCfg = Conf.getValue("addons.javaServer") || {};
    if (!javaCfg.enable) {
      data.code = -1;
      data.msg = "addon not enabled!";
      return data;
    }

    await Addon.get("javaServer").createServer();

    data.server = "http://localhost:" + javaCfg.port;

    return data;
  }

  /**
   * 废弃，请使用 cross 模块
   * 关闭java项目
   */
  async closeJavaServer() {
    let data = {
      code: 0,
      msg: "",
    };
    const javaCfg = Conf.getValue("addons.javaServer") || {};
    if (!javaCfg.enable) {
      data.code = -1;
      data.msg = "addon not enabled!";
      return data;
    }

    await Addon.get("javaServer").kill();

    return data;
  }

  /**
   * 废弃，请使用 cross 模块
   * java运行状态
   */
  async runStatus() {
    let data = {
      code: 0,
      msg: "",
      flag: false,
    };
    const flag = await Addon.get("javaServer").check();
    //Log.info("[FrameworkController:runStatus] flag-----------"+flag);
    data.flag = flag;

    return data;
  }

  /**
   * 任务
   */
  someJob(args, event) {
    let jobId = args.id;
    let action = args.action;

    let result;
    switch (action) {
      case "create":
        result = Services.get("framework").doJob(jobId, action, event);
        break;
      case "close":
        Services.get("framework").doJob(jobId, action, event);
        break;
      case "pause":
        Services.get("framework").doJob(jobId, action, event);
        break;
      case "resume":
        Services.get("framework").doJob(jobId, action, event);
        break;
      default:
    }

    let data = {
      jobId,
      action,
      result,
    };
    return data;
  }

  /**
   * 创建任务池
   */
  async createPool(args, event) {
    let num = args.number;
    Services.get("framework").doCreatePool(num, event);

    // test monitor
    Services.get("framework").monitorJob();

    return;
  }

  /**
   * 通过进程池执行任务
   */
  someJobByPool(args, event) {
    let jobId = args.id;
    let action = args.action;

    let result;
    switch (action) {
      case "run":
        result = Services.get("framework").doJobByPool(jobId, action, event);
        break;
      default:
    }

    let data = {
      jobId,
      action,
      result,
    };
    return data;
  }

  /**
   * 测试接口
   */
  hello(args) {
    Log.info("hello ", args);
  }
}

FrameworkController.toString = () => "[class FrameworkController]";
module.exports = FrameworkController;
